home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ddj1190.arc / CRAMER.ASC < prev    next >
Text File  |  1990-10-27  |  22KB  |  698 lines

  1. _CTRACE: A MESSAGE LOGGING CLASS_
  2. by William D. Cramer
  3.  
  4. [LISTING ONE] 
  5.  
  6. /** CTrace.h -- Definitions for using the Trace class **/
  7. #define _H_CTrace
  8.  
  9. /* System/library header files */
  10. #include <Commands.h>        /* standard menu command definition */
  11. #include <oops.h>        /* standard OOP definitions */
  12. #include <stdarg.h>        /* varg macro definitions */
  13. #include <CDesktop.h>        /* definitions for desktop class */
  14. #include <CBartender.h>     /* definitions for menu bar manager */
  15. #include <CDataFile.h>        /* definitions for data file class */
  16. #include <CApplication.h>    /* definitions for the application class */
  17. #include <CDocument.h>        /* definitions for parent class */
  18. #include <Constants.h>        /* miscellaneous environment constants */
  19.  
  20. /* Local header files */
  21. #include "CLogPanorama.h"    /* definitions for logging panorama class */
  22.  
  23. /* Resource numbers */
  24. #define TRACE_MENU_ID      (2000)      /* menu resource ID */
  25. #define TRACE_MENU_SHOW   (2000L)     /* menu command for show/hide log */
  26. #define TRACE_MENU_MASK   (2001L)     /* menu command for log masking */
  27. #define TRACE_WINDOW_ID   (2000)      /* main window resource ID */
  28. #define TRACE_MASK_DIALOG (2000)      /* resource ID for dialog box */
  29. #define FIRST_MASK       (3)           /* item # of first checkbox in dialog */
  30. #define LAST_MASK       (34)          /* item # of last checkbox in dialog */
  31. #define UNHILITE_CONTROL   (255)      /* magic part # for disabling control */
  32. #define OKAY_BUTTON_ITEM    (1)          /* item # for the 'okay' button */
  33. #define CANCEL_BUTTON_ITEM  (2)          /* item # for the 'cancel' button */
  34.  
  35. /* Standard trace categories */
  36. #define T_ERROR     (0x00000001)        /* serious error */
  37. #define T_WARNING    (0x00000002)        /* mildly serious problem */
  38. #define T_INFO        (0x00000004)        /* news you can use */
  39. #define T_FUNC_IN    (0x00000008)        /* function entry */
  40. #define T_FUNC_OUT    (0x00000010)        /* function exit */
  41.  
  42. /* Other constants */
  43. #define MAX_USER_BUFF (MAX_LOGREC_CHAR-19+1)  /* max length of user message */
  44. #define TRACE_DEFAULT_MASK    (0L)          /* initial trace mask */
  45.  
  46. /* External references */
  47. extern CDesktop     *gDesktop;        /* the whole desktop view */
  48. extern CApplication    *gApplication;        /* the application object */
  49. extern CBartender    *gBartender;        /* the menu bar object */
  50. extern OSType        gSignature;        /* application signature */
  51. struct CTrace : CDocument
  52.     {
  53.     /* local instance variables */
  54.     CLogPanorama  *itsLogPanorama; /* panorama for trace messages */
  55.     unsigned long currMask;        /* currently enabled trace categories */
  56.     /* local class methods */
  57.     void    ITrace(short records);
  58.     void    ToggleTraceWindow(void);
  59.     void    SetTraceMask (void);
  60.     void    Trace (unsigned long mask, char *format, ...);
  61.     Boolean IsItVisible(void);
  62.     /* inherited methods overriden */
  63.     void    UpdateMenus (void);
  64.     Boolean DoSaveAs (SFReply *macSFReply);
  65.     Boolean Close (Boolean quitting);    
  66.     };
  67.  
  68.  
  69. [LISTING TWO] 
  70.  
  71. /** CTrace.c -- Methods for the trace document class. **/
  72. #include "CTrace.h"        /* trace class parameters */
  73.  
  74. /** Global declaration **/
  75. CTrace
  76.     *gTrace;        /* the one instance of this class */
  77.     
  78. /** ITrace() -- Initializes trace document object. **/
  79. void CTrace::ITrace
  80.     (
  81.     short records        /* number of records before wrap */
  82.     )
  83. {
  84. Rect
  85.     frameRect;        /* window frame */
  86. CDocument::IDocument (gApplication, TRUE);
  87. itsWindow = new (CWindow);
  88. itsWindow->IWindow (TRACE_WINDOW_ID, FALSE, gDesktop, this);
  89. itsWindow->GetFrame (&frameRect);
  90. itsWindow->Move (gDesktop->bounds.right - frameRect.right - RIGHT_SMARGIN,gDesktop->bounds.top + TOP_SMARGIN);
  91. itsLogPanorama = new (CLogPanorama);
  92. itsLogPanorama->ILogPane (records, this, itsWindow);
  93. itsMainPane = itsLogPanorama;
  94. currMask = TRACE_DEFAULT_MASK;
  95. gTrace = this;
  96. }
  97.  
  98. /** ToggleTraceWindow() -- Toggles visibility of trace window. **/
  99. void CTrace::ToggleTraceWindow(void)
  100. {
  101. if (itsWindow->visible)
  102.     itsWindow->Hide ();
  103. else
  104.     {
  105.     itsWindow->Show ();
  106.     itsWindow->Select ();
  107.     }
  108. }
  109.  
  110. /** Close() -- Overrides normal document method by closing trace window. **/
  111. Boolean CTrace::Close 
  112.     (
  113.     Boolean quitting                /* ignored */
  114.     )
  115. {
  116. itsWindow->Hide ();
  117. return (TRUE);
  118. }
  119.  
  120. /** SetTraceMask -- Allows user to set/clear defined trace masks.**/
  121. void CTrace::SetTraceMask (void)
  122. {
  123. int 
  124.     bitNum,         /* bit number within the trace mask */
  125.     checkBoxState,        /* state of a checkbox (0=unset,1=set) */
  126.     item,            /* loop counter */
  127.     itemType,        /* item type (4=button, 5=checkbox) */
  128.     whichItem;        /* item number selected by user */
  129. Handle 
  130.     itemStuff;        /* handle to dialog item parameters */
  131. Boolean 
  132.     done;            /* loop-termination flag */
  133. Str255 
  134.     title;            /* text associated with a dialog item */
  135. Rect 
  136.     itemRect;        /* rectangle surrounding a control */
  137. DialogPtr
  138.     maskDialog;        /* structure for dialog box */
  139. /* Pull up the mask dialog box out of the resource fork */
  140. maskDialog = GetNewDialog (TRACE_MASK_DIALOG, NULL, (Ptr)(-1));
  141.  
  142. /* Run through checkboxes */
  143. for (item=FIRST_MASK, bitNum=0; 
  144.         item<=LAST_MASK; item++, 
  145.         bitNum++)
  146.     {
  147.     GetDItem (maskDialog, item, &itemType, &itemStuff, &itemRect);    
  148.     GetCTitle ( (ControlHandle)itemStuff, title);
  149.     PtoCstr ((char*)title);
  150.     if (strcmp((char*)title, "Undefined") != 0)
  151.         {
  152.         checkBoxState = ((currMask&(1L<<bitNum)) == 0L) ? 0 : 1;
  153.         SetCtlValue ( (ControlHandle) itemStuff, checkBoxState);
  154.         }
  155.     else
  156.         HiliteControl (itemStuff, UNHILITE_CONTROL);
  157.     }
  158. /* The default button (#1) is the okay button, draw outline around it. */
  159. GetDItem (maskDialog, OKAY_BUTTON_ITEM, &itemType, &itemStuff, &itemRect);
  160. SetPort (maskDialog);
  161. PenSize (3, 3);
  162. InsetRect (&itemRect, -4, -4);
  163. FrameRoundRect (&itemRect, 16, 16);    
  164.  
  165. /* Get events from dialog manager and process accordingly */
  166. done = FALSE;
  167. while (!done)
  168.     {
  169.     ModalDialog (NULL, &whichItem);
  170.     GetDItem (maskDialog, whichItem, &itemType, &itemStuff, &itemRect);
  171.     switch (itemType)
  172.         {
  173.         case ctrlItem + btnCtrl :    /* CANCEL or OKAY */
  174.             if (whichItem == OKAY_BUTTON_ITEM)
  175.         {
  176.         currMask = 0L;    
  177.          for (item=FIRST_MASK, bitNum=0; item<=LAST_MASK; item++, bitNum++)
  178.         {
  179.         GetDItem (maskDialog, item, &itemType, &itemStuff, &itemRect);
  180.              checkBoxState = GetCtlValue ( (ControlHandle) itemStuff);
  181.                currMask |= (checkBoxState==0) ? 0L : (1L<<bitNum);
  182.         }
  183.         done = TRUE;
  184.         }
  185.         else if (whichItem == CANCEL_BUTTON_ITEM)
  186.         done = TRUE;
  187.         break;
  188.     case ctrlItem + chkCtrl :    /* a category checkbox */
  189.         checkBoxState = GetCtlValue ( (ControlHandle) itemStuff);
  190.             if (checkBoxState == 0)
  191.         SetCtlValue ( (ControlHandle) itemStuff, 1);
  192.             else
  193.         SetCtlValue ( (ControlHandle) itemStuff, 0);
  194.             break;
  195.         default:
  196.             break;
  197.         }
  198.     }
  199.  
  200. /* On exit, trash dialog record and controls */
  201. DisposDialog (maskDialog);
  202. }
  203.  
  204. /** Trace() -- Checks current mask **/
  205. void CTrace::Trace
  206.     (
  207.     unsigned long mask,        /* severity of message */
  208.     char *format,            /* format for user's arguments */
  209.     ...                /* arguments to format (varg) */
  210.     )
  211. {
  212. static char 
  213.     traceBuff[MAX_LOGREC_CHAR],    /* string that will be added to log */
  214.     userBuff[MAX_LOGREC_CHAR*2],    /* user's contribution to log record */
  215.     prefix[40];            /* date+time string */
  216. int
  217.     maxUserBuff;        /* maximum length of formatted user string */
  218. long    
  219.     timeSecs;        /* current time/date */
  220. DateTimeRec
  221.     dateRec;        /* time/date in MM/DD/YY HH:MM:SS components */
  222. /* Should the message get added to the trace log? */
  223. if ( (currMask & mask) != 0)
  224.     {
  225.     /* format the user's portion of the message */
  226.     vsprintf (userBuff, format, __va(format));
  227.     /* make sure the entire record will fit into traceBuff */
  228.     if (strlen (userBuff) > MAX_USER_BUFF)
  229.         userBuff[MAX_USER_BUFF] = NULL;
  230.     /* build log message and add it to the log */
  231.     GetDateTime (&timeSecs);
  232.     Secs2Date (timeSecs, &dateRec);
  233.     sprintf (traceBuff, "%02d/%02d/%02d--%02d:%02d:%02d %s", 
  234.             dateRec.month, dateRec.day, dateRec.year-1900, 
  235.             dateRec.hour, dateRec.minute, dateRec.second,
  236.             userBuff);
  237.     itsLogPanorama->AddString (traceBuff);
  238.     }
  239. }
  240.  
  241. /** IsItVisible() -- Returns 'visible' flag to update menu bar entries. **/
  242. Boolean CTrace::IsItVisible(void)
  243. {
  244. return (itsWindow->visible);
  245. }
  246.  
  247. /** UpdateMenus() -- Disables Save and Revert entries **/
  248. void CTrace::UpdateMenus(void)
  249. {
  250. inherited::UpdateMenus ();;
  251. gBartender->DisableCmd (cmdSave);
  252. gBartender->DisableCmd (cmdRevert);
  253. }
  254.  
  255. /** DoSaveAs() -- Writes out contents of itsLogList to indicated file. **/
  256. Boolean CTrace::DoSaveAs 
  257.     (
  258.     SFReply *macSFReply        /* the user's choice of file */
  259.     )
  260. {
  261. char    
  262.     logRecBuff[MAX_LOGREC_CHAR];    /* buffer for log entry */
  263. short    
  264.     maxRec,             /* number of records in LogList */
  265.     offsetToNull,            /* byte offset to end of log entry */
  266.     rec;                /* loop counter */
  267. /* Dispose of the data used for the old file record */
  268. if (itsFile != NULL)
  269.     itsFile->Dispose ();
  270. /* Set up the new data file (no error checking!) */
  271. itsFile = new (CDataFile);
  272. ((CDataFile *)itsFile)->IDataFile ();
  273. itsFile->SFSpecify (macSFReply);
  274. itsFile->CreateNew (gSignature, 'TEXT');
  275. itsFile->Open (fsRdWrPerm);
  276.  
  277. /*  Write out all records in list (add carriage return to end of each line).*/
  278. maxRec = (short)(itsLogPanorama->itsLogList)->GetNumItems();
  279. for (rec=1; rec<=maxRec; rec++) 
  280.     {
  281.     (itsLogPanorama->itsLogList)->GetString (rec, logRecBuff);
  282.     offsetToNull = strlen (logRecBuff);
  283.     logRecBuff[offsetToNull] = '\r';
  284.     ((CDataFile*)itsFile)->WriteSome (logRecBuff, offsetToNull+1);
  285.     }        
  286. return (TRUE);
  287. }
  288.  
  289.  
  290.  
  291. [LISTING THREE] 
  292.  
  293. /** CLogPanarama.h -- Definitions for using the LogPanorama class **/
  294. #define _H_CLogPanorama
  295.  
  296. /* System/library headers */
  297. #include <CPanorama.h>        /* definitions for superclass Panorama */
  298. #include <CScrollPane.h>    /* definitions for ScrollPane class */
  299. #include <CWindow.h>        /* definitions for Window class */
  300. #include <oops.h>        /* standard OOP definitions */
  301. #include <Constants.h>        /* miscellaneous look-n-feel paramaters */
  302. #include <Limits.h>        /* numeric extrema */
  303.  
  304. /* Local headers */
  305. #include "CLogList.h"        /* definitions for LogList class */
  306.  
  307. #define LOGPANE_FONT    (monaco)    /* font family of text in the log window */
  308. #define LOGPANE_FONT_SIZE    (9) /* size of text in the log window */
  309. #define LOGPANE_HORZ_SCROLL    (5) /* units per horizontal scroll */
  310. #define LOGPANE_VERT_SCROLL    (1) /* units per vertical scroll */
  311. #define LOGPANE_INSET        (4) /* left margin for start of text */
  312.  
  313. /* Externals referenced */
  314. extern RgnHandle    
  315.     gUtilRgn;                /* drawing region */
  316. struct CLogPanorama : CPanorama
  317.     {
  318.     /* local class instance data */
  319.     CLogList    *itsLogList;    /* the buffer for logged data */
  320.     /* local class methods */
  321.     void    ILogPane (short records, CBureaucrat *aSupervisor, CWindow *anEnclosure);
  322.     void    AddString (char *theString);
  323.     /* inherited methods overriden */
  324.     void    Draw (Rect *theRect);
  325.     };
  326.  
  327.  
  328.  
  329. [LISTING FOUR]
  330.  
  331. /** CLogPanorama.c -- Methods for a CLogPanorama class object. **/
  332. #include "CLogPanorama.h"                /* defines log class */
  333.  
  334. /** ILogPanorama -- Initializes an instance of the log panorama class. **/
  335. void CLogPanorama::ILogPane
  336.     (
  337.     short records,            /* number of records in LogList */
  338.     CBureaucrat    *aSupervisor,    /* in-charge for this panorama */
  339.     CWindow *aWindow        /* window object to place pane into */
  340.     )
  341. {
  342. FontInfo
  343.     fontParms;            /* paramaters of selected font */
  344. short    
  345.     lineSpace,            /* pixels per line */
  346.     charSpace;            /* pixels per widest character */
  347. Rect    
  348.     maxWindowRect,            /* maximum growth of log window */
  349.     marginRect;            /* inside margins of viewable area */
  350. CScrollPane
  351.     *theScrollPane;         /* pane associated with panorama */
  352.     
  353. /* Set drawing parameters and adjust record size, if necessary. **/
  354. aWindow->Prepare ();
  355. TextFont (LOGPANE_FONT);
  356. TextSize (LOGPANE_FONT_SIZE);
  357. GetFontInfo (&fontParms);
  358. lineSpace = fontParms.ascent+fontParms.descent+fontParms.leading;
  359. charSpace = fontParms.widMax;
  360. if ( ((long)records*(long)lineSpace) > (long)INT_MAX)
  361.     records = INT_MAX / lineSpace;
  362. SetRect (&maxWindowRect, MIN_WSIZE, MIN_WSIZE, 
  363.         (MAX_LOGREC_CHAR * charSpace) + SBARSIZE, 
  364.         (records * lineSpace) + SBARSIZE);
  365. aWindow->SetSizeRect (&maxWindowRect);
  366.  
  367. /* Initialize Panorama's ScrollPane, set scroll units to the defaulted 
  368. ** values, and attach the Panorama to the ScrollPane. */
  369. theScrollPane = new (CScrollPane);
  370. theScrollPane->IScrollPane(aWindow, this, 0, 0, 0, 0,sizELASTIC, sizELASTIC,TRUE, TRUE, TRUE);
  371. theScrollPane->FitToEnclFrame (TRUE, TRUE);
  372. theScrollPane->SetSteps (LOGPANE_HORZ_SCROLL, LOGPANE_VERT_SCROLL);
  373.  
  374. /* Initialize Panarama to include maximum chars wide and maximum records tall,
  375. ** set the Panarama units to one char wide and one char tall. */
  376. CPanorama::IPanorama(theScrollPane, aSupervisor, MAX_LOGREC_CHAR, 
  377.         records, 0, 0, sizELASTIC, sizELASTIC);
  378. SetScales (charSpace, lineSpace);
  379. FitToEnclosure (TRUE, TRUE);
  380. theScrollPane->InstallPanorama (this);
  381.  
  382. /*  Create the LogList and initialize. */
  383. itsLogList = new (CLogList);
  384. itsLogList->ILogList (records);
  385. }
  386.  
  387. /** Draw() -- Refreshes the visible portion of the window. **/ 
  388. void CLogPanorama::Draw
  389.     (
  390.     Rect *drawRect        /* portion of window to refresh */
  391.     )
  392. {
  393. short    
  394.     firstRec,        /* record number of first visible line */
  395.     hScale,         /* how many pixels wide is a character? */
  396.     lastRec,        /* record number of last line */
  397.     totalRec,        /* total number of records in LogList */
  398.     vScale;         /* how many pixels tall is a line? */ 
  399. register short
  400.     currRow,        /* window coordinates of current row */
  401.     rec;            /* loop counter */
  402. char 
  403.     buff[MAX_LOGREC_CHAR];    /* buffer for fetching log records */
  404. /*  First, translate draw rectangle to records. **/
  405. GetScales (&hScale, &vScale);
  406. totalRec = (short)itsLogList->GetNumItems ();
  407. firstRec = (drawRect->top / vScale);
  408. if (firstRec == 0)
  409.     firstRec = 1;
  410. lastRec = (drawRect->bottom / vScale) + 1;
  411. if (lastRec > totalRec)
  412.     lastRec = totalRec;
  413. /*  Refresh all of visible lines. **/
  414. Prepare ();
  415. for (rec=firstRec, currRow=firstRec*vScale;
  416.         rec<=lastRec;
  417.         rec++, currRow+=vScale)
  418.     {
  419.     itsLogList->GetString (rec, buff);
  420.     MoveTo (LOGPANE_INSET, currRow);
  421.     DrawString (CtoPstr(buff));
  422.     }
  423. }
  424.  
  425. /** AddString() -- Adds a new string to panorama. **/
  426. void CLogPanorama::AddString
  427.     (
  428.     char *theString        /* null-terminated string to add */
  429.     )
  430. {
  431. Rect
  432.     frameRect;        /* interior of current frame */
  433. short
  434.     listLimits,        /* maximum the LogList will hold */
  435.     hSpan,            /* the horizontal span of frame */
  436.     vSpan,            /* the vertical span of frame */
  437.     hScale,         /* horizontal pixels in panarama unit */
  438.     vScale;         /* vertical pixels in panarama unit */
  439. Point
  440.     topRecord,        /* LogList record number of top row */
  441.     bottomRecord,        /* LogList record number of bottom row */
  442.     newRecord,        /* LogList record number of new row */
  443.     currPosition,        /* panorama coordinates of top/left frame */
  444.     recPosition;        /* panorama coordinates of new string */
  445. /*  Add the record to the LogList. */
  446. itsLogList->AddString (theString);
  447. /*  Get coordinates of current frame and calculate tentative coordinates for 
  448. newly added record. */
  449. GetPosition (&currPosition);
  450. GetFrameSpan (&hSpan, &vSpan);
  451. GetScales (&hScale, &vScale);
  452. topRecord.v = currPosition.v + 1;
  453. bottomRecord.v = topRecord.v + vSpan - 1;
  454. newRecord.v = (short)itsLogList->GetNumItems ();
  455. newRecord.h = currPosition.h;
  456.  
  457. /* Determine where we are in reference to bottom of screen and of list. **/
  458. if (newRecord.v > (bottomRecord.v+1) )
  459.     {
  460.     /* bottom record isn't visible */
  461.     currPosition.v = newRecord.v - vSpan;
  462.     ScrollTo (currPosition, FALSE);
  463.     GetInterior (&frameRect);
  464.     Prepare ();
  465.     EraseRect (&frameRect);
  466.     }
  467. else
  468.     {
  469.     /* bottom record is visible */
  470.     listLimits = itsLogList->GetMaxRecordCount ();
  471.     if (bottomRecord.v < listLimits)
  472.         {
  473.         /* room in list--create blank line if necessary */
  474.         if (newRecord.v == (bottomRecord.v + 1) )
  475.             {
  476.             Scroll (0, 1, TRUE);
  477.             SetRect (&frameRect, newRecord.h*hScale, (newRecord.v-1)*vScale,(newRecord.h+hSpan)*hScale, (newRecord.v)*vScale);
  478.             }
  479.         else
  480.            SetRect (&frameRect, newRecord.h*hScale, (newRecord.v-1)*vScale,
  481.                    (newRecord.h+hSpan-1)*hScale, (newRecord.v)*vScale);
  482.         }    
  483.     else if (bottomRecord.v > listLimits)
  484.         {
  485.         currPosition.v = newRecord.v - vSpan;
  486.         ScrollTo (currPosition, FALSE);
  487.         GetInterior (&frameRect);
  488.         Prepare ();
  489.         EraseRect (&frameRect);
  490.         }
  491.     else
  492.         {
  493.       /* bottom of pane=limit of list, so do our own scrolling */
  494.         Prepare ();
  495.         GetInterior (&frameRect);
  496.         ScrollRect (&frameRect, 0, -vScale, gUtilRgn);
  497.      SetRect (&frameRect, bottomRecord.h*hScale, (bottomRecord.v-1)*vScale,(bottomRecord.h+hSpan-1)*hScale, (bottomRecord.v)*vScale);
  498.         EraseRect (&frameRect);
  499.         }
  500.     }        
  501. Draw (&frameRect);
  502. itsScrollPane->Calibrate();
  503. }
  504.  
  505.  
  506. [LISTING FIVE]
  507.  
  508. /** CLogList.h -- Definitions for a LogList object. **/
  509. #define _H_CLogList
  510.  
  511. #include <CList.h>        /* definitions for superclass */
  512. #include <oops.h>        /* standard OOP definitions */
  513. #include <string.h>        /* miscellaneous string definitions */
  514.  
  515. #define MAX_LOGREC_CHAR (200L)    /* size of longest entry (inc NULL) */
  516.  
  517. struct CLogList : CList
  518.     {
  519.     /* internal instance data */
  520.     short        maxRec;     /* maximum number of records */
  521.     /* local class methods */
  522.     void    ILogList (short records);
  523.     void    AddString (char *theString);
  524.     void    GetString (short which, char *theString);
  525.     short    GetMaxRecordCount (void);
  526.     /* inherited methods overriden */
  527.     void    Dispose (void);
  528.     };
  529.  
  530.  
  531. [LISTING SIX] 
  532.  
  533. /** CLogList.c -- Methods for a LogList object. **/
  534.  
  535. #include "CLogList.h"        /* definitions for LogList class */
  536.     
  537. /** ILogList -- Initializes a LogList for the indicated number of entries. **/
  538. void CLogList::ILogList
  539.     (
  540.     short records        /* maximum number of entries */
  541.     )
  542. {
  543. CList::IList ();
  544. maxRec = records;        
  545. }
  546.  
  547. /** Dispose -- Frees all records (and their handles) in the list **/
  548. void CLogList::Dispose (void)
  549. {
  550. short 
  551.     i;                /* loop counter */
  552. Handle 
  553.     record;             /* handle to list record */
  554. while (GetNumItems() > 0) 
  555.     {
  556.     record = (Handle)FirstItem();
  557.     Remove ((CObject*)record);
  558.     DisposHandle (record);
  559.     }
  560. }
  561.  
  562. /** AddString -- Adds a string to LogList. **/ 
  563. void CLogList::AddString 
  564.     (
  565.     char *theString     /* pointer to null-terminated string */
  566.     )
  567. {
  568. Handle    
  569.     record;         /* handle for a list entry */
  570. if (strlen(theString)+1 < MAX_LOGREC_CHAR)
  571.     {
  572.     record = NewHandle (strlen(theString)+1);
  573.     strcpy (*record, theString);
  574.     }
  575. else
  576.     {
  577.     record = NewHandle (MAX_LOGREC_CHAR);
  578.     strncpy (*record, theString, MAX_LOGREC_CHAR);
  579.     *record[MAX_LOGREC_CHAR-1] = NULL;
  580.     }
  581. Append ((CObject*)record);
  582. if (GetNumItems () > maxRec)
  583.     {
  584.     record = (Handle)FirstItem ();    
  585.     Remove ((CObject*)record);
  586.     DisposHandle (record);
  587.     }
  588. }
  589.  
  590. /** GetString -- Grabs requested entry and copies it to user's buffer. **/
  591. void CLogList::GetString 
  592.     (
  593.     short which,        /* record number to return */
  594.     char *theString     /* point to destination buffer */
  595.     )
  596. {
  597. Handle 
  598.     record;         /* handle for a list entry */
  599. if ( (record=(Handle)NthItem(which)) != NULL)
  600.     strcpy (theString, *record);
  601. else
  602.     theString[0] = 0;
  603. }
  604.  
  605. /** GetMaxRecordCount -- Returns max.number of records available in LogList **/
  606. short CLogList::GetMaxRecordCount (void)
  607. {
  608. return (maxRec);
  609. }
  610.  
  611.  
  612.  
  613. [LISTING SEVEN]
  614.  
  615. /** CMyApp.c -- Demonstrates how to include the CTrace utility as part of your
  616. ** application. Functions it performs are showing/hiding the trace log window
  617. ** and setting the trace mask. To demonstrate the calls to Trace(), 
  618. ** it uses the New and Open menu commands. **/
  619.  
  620. #include <CApplication.h>        /* Application class definitions */
  621. #include <CBartender.h>         /* Bartender class definitions */
  622. #include <Commands.h>            /* standard command definitions */
  623. #include "CTrace.h"            /* Trace log class definitions */
  624.  
  625. /* external references */
  626. extern CBartender *gBartender;
  627. extern CTrace *gTrace;
  628.  
  629. /* Declare the application class */
  630. struct CMyApp : CApplication
  631.     {
  632.     CTrace    *itsTraceLog;
  633.     void    IMyApp (void);
  634.     void    DoCommand(long c);
  635.     void    UpdateMenus(void);
  636.     };
  637.     
  638. /** ITestApp -- Initializes the application and the CTrace object. **/
  639. void CTestApp::ITestApp(void)
  640. {
  641. CApplication::IApplication (4, 20480L, 2048L);
  642. itsTraceLog = new (CTrace);
  643. itsTraceLog->ITrace (100);
  644. }
  645.  
  646. /** ITestApp -- Updates the Trace portion of the menus. **/
  647. void CTestApp::UpdateMenus (void)
  648. {
  649. inherited::UpdateMenus ();
  650. gBartender->EnableMenu (TRACE_MENU_ID);
  651. gBartender->EnableCmd (TRACE_MENU_SHOW);
  652. gBartender->EnableCmd (TRACE_MENU_MASK);
  653. if (itsTraceLog->IsItVisible ())
  654.     gBartender->CheckMarkCmd (TRACE_MENU_SHOW, TRUE);
  655. else
  656.     gBartender->CheckMarkCmd (TRACE_MENU_SHOW, FALSE);
  657. }
  658.  
  659. /** ITestApp -- Processes application commands. **/
  660. void CTestApp::DoCommand (long command)
  661. {
  662. int 
  663.     i;            /* a loop counter */
  664. static 
  665.     int addno=1;        /* a counter for the demo adds */
  666. switch (command)
  667.     {
  668.     case cmdNew :        /* trace one value at mask TRACE_INFO */
  669.         gTrace->Trace (T_INFO, "one'sies add, data=%d", addno++);
  670.         break;
  671.     case cmdOpen :        /* trace 32 messages, one at each mask value */
  672.       for (i=0; i<32; i++)
  673.         gTrace->Trace ((1L<<i), "Entry #%d, trace mask #%d (mask=0x%08lX)",addno++, i+1, (long)(1L<<i));
  674.       break;
  675.     case TRACE_MENU_SHOW :
  676.         itsTraceLog->ToggleTraceWindow ();
  677.         break;
  678.     case TRACE_MENU_MASK :
  679.         itsTraceLog->SetTraceMask ();
  680.         break;
  681.     default :
  682.         inherited::DoCommand (command);
  683.     }
  684. }
  685.  
  686. /** main() -- Main routine of the demo program. **/
  687. void main ()
  688. {
  689. gApplication = new (CTestApp);
  690. ((CTestApp*)gApplication)->ITestApp ();
  691. gApplication->Run ();
  692. gApplication->Exit ();
  693. }
  694.  
  695.  
  696.  
  697.  
  698.